package com.dwxt.gateway.config;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.netty.channel.BootstrapHandlers;

import java.time.Duration;
import java.util.concurrent.atomic.AtomicBoolean;

import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.NANOSECONDS;

@Configuration
public class NettyConfig {
    @Bean
    public WebServerFactoryCustomizer<NettyReactiveWebServerFactory> idleTimeoutCustomizer(

            @Value("${server.netty.idle-timeout}") int idleTimeout) {
        return factory -> factory.addServerCustomizers(

                server -> server.tcpConfiguration(

                        tcp -> tcp.bootstrap(bootstrap -> {
                                    //增加如下代码，从而可保持原有配置并追加保活
                                    BootstrapHandlers.updateConfiguration(bootstrap, "IdleStateHandler",

                                            (connectionObserver, channel) -> {
                                                channel.pipeline().addLast(new IdleStateHandler(0, 0,

                                                        idleTimeout, MINUTES) {
                                                    private final AtomicBoolean closed = new AtomicBoolean();

                                                    @Override

                                                    protected void channelIdle(ChannelHandlerContext ctx,

                                                                               IdleStateEvent evt) {
                                                        if (closed.compareAndSet(false, true)) {
                                                            ctx.close();
                                                        }
                                                    }
                                                });

                                            });

                                    return bootstrap;
                                }

                        )));

    }

}

